package com.inspur.edp.web.form.process.service;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.inspur.edp.web.form.process.entity.FarrisContainerType;
import com.inspur.edp.web.form.process.entity.FormButtonTree;
import com.inspur.edp.wf.bizprocess.entity.FormButton;
import com.inspur.edp.wf.bizprocess.entity.FormField;
import com.inspur.edp.wf.bizprocess.entity.FormFieldData;

import java.util.*;

/**
 * 移动低代码表单把按钮和字段，推送到工作流。
 */
public class MobileWFFormFormatManager {
    private static final String FORM_CONTAINER_TYPE = "form-col-1";

    private MobileWFFormFormatManager() {
    }

    /**
     * 静态单例属性
     */
    private static final MobileWFFormFormatManager Instance = new MobileWFFormFormatManager();



    public static  MobileWFFormFormatManager getInstance() {
        return MobileWFFormFormatManager.Instance;
    }

    public List<FormButton> getButtons(JsonNode formContent, String formatId) {
        JsonNode formType = formContent.at("/options/formType");
        boolean isZeroForm = formType != null && "fromNoCode".equals(formType.asText());

        // 递归 找 Toolbar，Button
        JsonNode componentArr = formContent.at("/module/components");
        FormButtonTree buttonTree = new FormButtonTree();
        componentArr.forEach(component->{
            //跳过列表页
            if( component.get("componentType") != null &&  "Page".equals(component.get("componentType").asText())
                    && ( component.get("pageType") == null || !"Card".equals(component.get("pageType").asText())) ){
                return;
            }
            searchComponentsForButton(component, buttonTree, formatId,isZeroForm);
        });

        List<FormButton> buttonList = new ArrayList<>();
        buttonTree.getChildren().forEach(tree -> buttonList.addAll(tree.getChildButtons()));
        return buttonList;
    }

    private void searchComponentsForButton(JsonNode root, FormButtonTree buttonTree, String formatId, boolean isZeroForm) {
        if(root.isArray()) {
            for (JsonNode jsonNode : root) {
                searchComponentsForButton(jsonNode, buttonTree, formatId,isZeroForm);
            }
        }
        if(root.isObject()){
            JsonNode type = root.get("type");
            //"NavigationBar",
            if(type != null && Arrays.asList("ListView","ToolBarArea","ToolBar","Button","ButtonGroup","Card","LightAttachment").contains(type.asText())){
                this.findButtons(root, buttonTree, formatId,isZeroForm);
            } else if(type != null && Arrays.asList("NavigationBar").contains(type.asText())) {
                //导航栏不做处理
            }else {
                Iterator<String> fieldNames = root.fieldNames();
                while(fieldNames.hasNext()) {
                    String fieldName = fieldNames.next();
                    JsonNode fieldValue = root.get(fieldName);
                    if(fieldValue.isArray() || fieldValue.isObject()){
                        searchComponentsForButton(fieldValue, buttonTree, formatId,isZeroForm);
                    }
                }
            }
        }
    }

    private void findButtons(JsonNode node, FormButtonTree buttonTree, String formatId, boolean isZeroForm){
        JsonNode type = node.get("type");
        switch (type.asText()){
            case "NavigationBar":{
                JsonNode toolbar =  node.get("toolbar");
                if(null == toolbar){
                    break;
                }
                ArrayNode items = (ArrayNode) toolbar.get("items");
                if(items !=null && items.size() > 0 ){
                    this.findComplexButtons( items, node , buttonTree,  formatId);
                }
                break;
            }
            case "ListView":{
                JsonNode swipeToolbar =  node.get("swipeToolbar");
                if(null == swipeToolbar){
                    break;
                }
                ArrayNode items = (ArrayNode) swipeToolbar.get("items");
                if(items !=null && items.size() > 0 ){
                    this.findComplexButtons( items, node , buttonTree,  formatId);
                }
                break;
            }
            case "ToolBarArea":
            case "ToolBar":{
                ArrayNode items = (ArrayNode) node.get("items");
                ArrayNode contents = (ArrayNode) node.get("contents");
                if((null == items || items.size() == 0 ) && contents.size() > 0){
                    searchComponentsForButton(contents, buttonTree, formatId,isZeroForm);
                    break;
                }
                if(items != null && items.size() > 0 ){
                    this.findComplexButtons( items, node , buttonTree,  formatId);
                }
                break;
            }
            case "Button":{
                findSingleButton(node, buttonTree, formatId);
                break;
            }
            case "ButtonGroup":{
                ArrayNode items = (ArrayNode) node.get("items");
                if(items != null && items.size() > 0 ){
                    this.findComplexButtons( items, node , buttonTree,  formatId);
                }
                break;
            }
            case "Card":{
                ArrayNode items = (ArrayNode) node.get("actions");
                if(items != null && items.size() > 0 ){
                    this.findComplexButtons( items, node , buttonTree,  formatId);
                }
                break;
            }
            case "LightAttachment":{
                this.findLightAttachmentButton( node , buttonTree,  formatId,isZeroForm);
                break;
            }

        }
    }

    /**
     * 查找简单按钮
     * @param node
     * @param formButtonTree
     * @param formatId
     */
    private void findSingleButton(JsonNode node, FormButtonTree formButtonTree, String formatId) {
        FormButtonTree treeNode = new FormButtonTree();
        // button 当前没有分组信息，用方法名暂时做分组名
        FormButton parent = new FormButton();
        parent.setId(UUID.randomUUID().toString());
        parent.setButtonId(node.get("id").asText());
        parent.setButtonName(node.get("click")==null?"":node.get("click").asText());
        treeNode.setData(parent);

        FormButtonTree childNode = new FormButtonTree();
        FormButton buttonData = new FormButton();
        buttonData.setId(UUID.randomUUID().toString());
        buttonData.setButtonId(node.get("id").asText());
        if(node.get("text") != null){
            buttonData.setButtonName(node.get("text").asText());
        }else if(node.get("title") != null){
            buttonData.setButtonName(node.get("title").asText());
        }else{
            buttonData.setButtonName("按钮");
        }
        buttonData.setFormFormatId(formatId);
        childNode.setData(buttonData);

        treeNode.getChildren().add(childNode);
        formButtonTree.getChildren().add(treeNode);
    }

    /**
     * 查找复杂按钮
     * @param childNodes 按钮项
     * @param parentNode 按钮父级信息（可能父父级）
     * @param formButtonTree
     * @param formatId
     */
    private void findComplexButtons(ArrayNode childNodes, JsonNode parentNode , FormButtonTree formButtonTree, String formatId){
        FormButtonTree treeNode = new FormButtonTree();
        FormButton parent = new FormButton();
        parent.setId(UUID.randomUUID().toString());
        parent.setButtonId(parentNode.get("id").asText());
        String title= parentNode.get("title") == null?"卡片":parentNode.get("title").textValue();
        parent.setButtonName(title);

        treeNode.setData(parent);
        childNodes.forEach(item -> {
            FormButtonTree button = new FormButtonTree();
            FormButton buttonData = new FormButton();
            buttonData.setId(UUID.randomUUID().toString());
            buttonData.setButtonId(item.get("id").asText());
            if(item.get("text") != null){
                buttonData.setButtonName(item.get("text").asText());
            }else if(item.get("title") != null){
                buttonData.setButtonName(item.get("title").asText());
            }else{
                buttonData.setButtonName("按钮");
            }
            buttonData.setFormFormatId(formatId);
            button.setData(buttonData);
            treeNode.getChildren().add(button);
        });
        formButtonTree.getChildren().add(treeNode);
    }

    /**
     * 查找附件
     * @param node
     * @param formButtonTree
     * @param formatId
     */
    private void findLightAttachmentButton(JsonNode node, FormButtonTree formButtonTree, String formatId,boolean isZeroForm) {
        if(isZeroForm){
            return;
        }
        FormButtonTree treeNode = new FormButtonTree();
        FormButton parent = new FormButton();
        parent.setId(UUID.randomUUID().toString());
        parent.setButtonId(node.get("id").asText());
        String title= node.get("title") == null?"卡片":node.get("title").textValue();
        parent.setButtonName(title);
        treeNode.setData(parent);

        FormButtonTree button_add = new FormButtonTree();
        FormButton buttonData_add = new FormButton();
        buttonData_add.setId(UUID.randomUUID().toString());
        buttonData_add.setButtonId(node.get("id").asText() + "_attachment_upload_btn");
        buttonData_add.setButtonName(node.get("text") == null ?"附件上传按钮":node.get("text").asText()+"上传按钮");
        buttonData_add.setFormFormatId(formatId);
        button_add.setData(buttonData_add);
        treeNode.getChildren().add(button_add);

        FormButtonTree button_remove = new FormButtonTree();
        FormButton buttonData_remove = new FormButton();
        buttonData_remove.setId(UUID.randomUUID().toString());
        buttonData_remove.setButtonId(node.get("id").asText() + "_attachment_delete_btn");
        buttonData_remove.setButtonName(node.get("text") == null ?"附件删除按钮":node.get("text").asText()+"删除按钮");
        buttonData_remove.setFormFormatId(formatId);
        button_remove.setData(buttonData_remove);
        treeNode.getChildren().add(button_remove);

        formButtonTree.getChildren().add(treeNode);
    }


    public List<FormFieldData> getFields(JsonNode formContent, String formatId) {
        FormFieldData root = new FormFieldData();
        JsonNode viewModelArr = formContent.at("/module/viewmodels");
        JsonNode componentArr = formContent.at("/module/components");
        componentArr.forEach(cmp -> {
            //找出卡片页面
            JsonNode containerTypeName = cmp.at("/componentType");

            boolean isLowCard = cmp.get("componentType") != null &&  "Page".equals(cmp.get("componentType").asText())
                    && cmp.get("pageType") != null && "Card".equals(cmp.get("pageType").asText());
            boolean isZeroCard = containerTypeName != null && FORM_CONTAINER_TYPE.equals(containerTypeName.asText());

            if( isLowCard  || isZeroCard){
                // module/components的节点都有componentType属性
                FormFieldData containerData = new FormFieldData();

                FormField container = new FormField();
                container.setId(UUID.randomUUID().toString());
                container.setFieldId(cmp.get("id").asText());
                container.setFieldName(cmp.get("title").asText());

                containerData.setData(container);
                containerData.setChildren(new ArrayList<>());

                root.getChildren().add(containerData);
                JsonNode form = this.findForm( cmp);
                if(form !=null && form.get("contents") !=null ){
                    extractFormControls(form.get("contents"), containerData, formatId);
                }
            }
        });
        return root.getChildren();
    }


    private void extractFormControls(JsonNode controls, FormFieldData containerData, String formatId) {
        if(controls != null && controls.size() > 0){
            FormFieldData fieldData;
            JsonNode child;
            for(int index = 0; index < controls.size(); index ++){
                child = controls.get(index);
                FormField field = new FormField();
                field.setId(UUID.randomUUID().toString());
                field.setFieldId(child.get("id").asText());
                field.setFieldName(child.get("title").asText());
                field.setFormFormatId(formatId);
                fieldData = new FormFieldData();
                fieldData.setData(field);
                fieldData.setChildren(new ArrayList<>());
                // 如果是fieldset 就把它的contents继续
                if(FarrisContainerType.FieldSet.name().equals(child.get("type").asText())){
                    extractFormControls(child.get("contents"), fieldData, formatId);
                }
                containerData.getChildren().add(fieldData);
            }
        }
    }

    private Map<String, String> findPageNames(JsonNode viewModelArr){
        Map<String, String> map = new HashMap<>();
        viewModelArr.forEach(vm -> {
            map.put(vm.get("id").asText(), vm.get("name").asText());
        });
        return map;
    }

    private JsonNode findForm(JsonNode cmp){
        if(cmp == null ){
            return null;
        }
        if("Form".equals(cmp.get("type").asText())){
            return cmp;
        }
        JsonNode result = null;
        if(cmp.get("contents") != null && cmp.get("contents").isArray()){
            for(JsonNode content:cmp.get("contents")) {
                result = this.findForm(content);
                if (result != null) {
                    break;
                }
            }
        }
        return result;
    }
}
